= ProgramNotInstalled String
| ProgramFailure String
-startExternalAddonProcess :: String -> [CommandParam] -> ExternalAddonPID -> Annex (Either ExternalAddonStartError ExternalAddonProcess)
-startExternalAddonProcess basecmd ps pid = do
+-- | Starts an external addon process that speaks a protocol over stdio.
+startExternalAddonProcessProtocol :: String -> [CommandParam] -> ExternalAddonPID -> Annex (Either ExternalAddonStartError ExternalAddonProcess)
+startExternalAddonProcessProtocol basecmd ps pid = do
errrelayer <- mkStderrRelayer
g <- Annex.gitRepo
cmdpath <- liftIO $ searchPath basecmd
-- using it.
newExternalState :: ExternalBackendName -> HasExt -> ExternalAddonPID -> Annex ExternalState
newExternalState ebname hasext pid = do
- st <- startExternalAddonProcess basecmd [] pid
+ st <- startExternalAddonProcessProtocol basecmd [] pid
st' <- case st of
Left (ProgramNotInstalled msg) -> warnonce msg >> return st
Left (ProgramFailure msg) -> warnonce msg >> return st
+git-annex (10.20250722) UNRELEASED; urgency=medium
+
+ * p2p: Added --enable option, which can be used to enable P2P networks
+ provided by external commands git-annex-p2p-<netname>
+
+ -- Joey Hess <id@joeyh.name> Wed, 30 Jul 2025 13:45:42 -0400
+
git-annex (10.20250721) upstream; urgency=medium
* Improved workaround for git 2.50 bug, avoding an occasional test suite
"uid" (withParams seek)
seek :: CmdParams -> CommandSeek
-seek = withWords (commandAction . start)
+seek = withWords (commandAction . start . Just)
-- This runs as root, so avoid making any commits or initializing
-- git-annex, or doing other things that create root-owned files.
-start :: [String] -> CommandStart
+start :: Maybe [String] -> CommandStart
#ifndef mingw32_HOST_OS
start os = do
#else
let si = SeekInput []
curruserid <- liftIO getEffectiveUserID
if curruserid == 0
- then case readish =<< headMaybe os of
- Nothing -> giveup "Need user-id parameter."
- Just userid -> go userid
+ then case os of
+ Just os' -> case readish =<< headMaybe os' of
+ Nothing -> giveup "Need user-id parameter."
+ Just userid -> go userid
+ Nothing -> giveup "Cannot run this command as root."
else starting "enable-tor" ai si $ do
gitannex <- fromOsPath <$> liftIO programPath
let ps = [Param (cmdname cmd), Param (show curruserid)]
{- git-annex command
-
- - Copyright 2016 Joey Hess <id@joeyh.name>
+ - Copyright 2016-2025 Joey Hess <id@joeyh.name>
-
- Licensed under the GNU AGPL version 3 or higher.
-}
import P2P.Address
import P2P.Auth
import P2P.IO
+import P2P.Generic
import qualified P2P.Protocol as P2P
import Git.Types
import qualified Git.Remote
import Utility.SafeOutput
import qualified Utility.FileIO as F
import qualified Utility.MagicWormhole as Wormhole
+import qualified Command.EnableTor as EnableTor
import Control.Concurrent.Async
import qualified Data.Text as T
= GenAddresses
| LinkRemote
| Pair
+ | Enable P2PNetName
optParser :: CmdParamsDesc -> Parser (P2POpts, Maybe RemoteName)
optParser _ = (,)
- <$> (pair <|> linkremote <|> genaddresses)
+ <$> (pair <|> linkremote <|> genaddresses <|> enable)
<*> optional name
where
genaddresses = flag' GenAddresses
( long "pair"
<> help "pair with another repository"
)
+ enable = Enable . P2PNetName <$> strOption
+ ( long "enable" <> metavar paramName
+ <> help "enable using a P2P network"
+ )
name = Git.Remote.makeLegalName <$> strOption
( long "name"
<> metavar paramName
seek (Pair, Nothing) = commandAction $ do
name <- unusedPeerRemoteName
startPairing name =<< loadP2PAddresses
+seek (Enable netname, _) = commandAction $
+ enableNetwork netname
unusedPeerRemoteName :: Annex RemoteName
unusedPeerRemoteName = go (1 :: Integer) =<< usednames
return LinkSuccess
go (Right Nothing) = return $ AuthenticationError "Unable to authenticate with peer. Please check the address and try again."
go (Left e) = return $ AuthenticationError $ "Unable to authenticate with peer: " ++ describeProtoFailure e
+
+enableNetwork :: P2PNetName -> CommandStart
+enableNetwork netname@(P2PNetName name)
+ | name == "tor" = EnableTor.start Nothing
+ | otherwise = starting "p2p enable" ai si $ next $ do
+ addrs <- liftIO $ getAddressGenericP2P netname
+ when (null addrs) $
+ giveup $ genericP2PCommand netname ++ " did not output any P2P addresses"
+ mapM_ storeP2PAddress addrs
+ return True
+ where
+ ai = ActionItemOther (Just (UnquotedString name))
+ si = SeekInput []
socketGenericP2P :: P2PNetName -> UnderlyingP2PAddress -> CreateProcess
socketGenericP2P netname (UnderlyingP2PAddress address) =
(proc (genericP2PCommand netname) ["socket", address])
- { std_in = CreatePipe
+ { std_out = CreatePipe
}
addressGenericP2P :: P2PNetName -> CreateProcess
addressGenericP2P netname =
(proc (genericP2PCommand netname) ["address"])
- { std_in = CreatePipe
+ { std_out = CreatePipe
}
getSocketGenericP2P :: P2PNetName -> UnderlyingP2PAddress -> IO (Maybe (OsPath, ProcessHandle))
getSocketGenericP2P netname address = do
- (Just hin, Nothing, Nothing, pid) <- createProcess $
+ (Nothing, Just hin, Nothing, pid) <- createProcess $
socketGenericP2P netname address
hGetLineUntilExitOrEOF pid hin >>= \case
Just l | not (null l) -> return $ Just (toOsPath l, pid)
getAddressGenericP2P :: P2PNetName -> IO [P2PAddress]
getAddressGenericP2P netname = do
- (Just hin, Nothing, Nothing, pid) <- createProcess $
+ (Nothing, Just hin, Nothing, pid) <- createProcess $
addressGenericP2P netname
go [] hin pid
where
n <- succ <$> readTVar (externalLastPid external)
writeTVar (externalLastPid external) n
return n
- AddonProcess.startExternalAddonProcess externalcmd externalparams pid >>= \case
+ AddonProcess.startExternalAddonProcessProtocol externalcmd externalparams pid >>= \case
Left (AddonProcess.ProgramFailure err) -> do
unusable err
Left (AddonProcess.ProgramNotInstalled err) ->
* `--enable <netname>`
Enable using the P2P network with the specified name.
- This needs the helper program `git-annex-p2p-<netname>` to be installed.
+
+ For networks other than tor, this needs the helper program
+ `git-annex-p2p-<netname>` to be installed.
After this command is run, `git annex remotedaemon` can be run to serve
incoming connections from peers, and `git-annex p2p --pair` or